Skip to content

Introduce ActorResolver methods, lightweight storage, and tests#2

Merged
inf3cti0n95 merged 8 commits into
mainfrom
feature/mdk-actor-interface
Jun 6, 2026
Merged

Introduce ActorResolver methods, lightweight storage, and tests#2
inf3cti0n95 merged 8 commits into
mainfrom
feature/mdk-actor-interface

Conversation

@inf3cti0n95

@inf3cti0n95 inf3cti0n95 commented Jun 6, 2026

Copy link
Copy Markdown
Member

Introduces specific implementations for the ActorResolver interface methods, a lightweight CloudProvider for local and memory storage, and updates auth tests.

Summary by CodeRabbit

  • Documentation

    • Added SECURITY.md and initial CHANGELOG (v0.1.0)
    • Updated Getting Started to use generated binary (bin/hyperrr) and new build/codegen flow
  • New Features

    • Built-in local disk and in-memory storage provider
    • Built-in CLI auth commands (apikey, user)
    • New default currency config (USD)
  • UI

    • Product listing now shows price as N/A / single price / min–max range with currency
  • Tests

    • Updated GraphQL, MCP/auth, and middleware tests/fixtures
  • Chores

    • CI workflow revised for multi-repo local workspace testing

…esigned product variant and pricing structures
- Added specific implementations for the ActorResolver interface methods: ID, Type, and Name.
- Updated the code generation logic to handle these methods appropriately.

feat: Introduce lightweight CloudProvider for local and memory storage

- Removed dependency on external cloud SDKs.
- Implemented a new CloudProvider that supports local filesystem and in-memory storage.
- Added methods for Upload, Open, Delete, and GetURL.

refactor: Update Actor type definitions for clarity

- Re-exported mdk.BaseActor for better compatibility and clarity in the identity package.

fix: Change ActorResolver method signature to return Actor instead of pointer

- Updated GetActorByAPIKey method to return identity.Actor directly.

test: Update auth tests to reflect changes in Actor methods

- Modified tests to use new Actor methods for ID, Type, and Name.
- Ensured compatibility with the updated Actor type.

chore: Add CHANGELOG and SECURITY.md for project documentation

- Created a CHANGELOG.md to document notable changes.
- Added SECURITY.md to outline the security policy and reporting process.
@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown

Complex PR? Review this PR in Change Stack to move by importance, not file order.

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Refactors actor identity to interface-typed actors, replaces gocloud blob storage with in-process mem/file providers, enriches product tests and GraphQL autobind, changes workflow handler resolution to registry lookups, registers built-in auth CLI commands, and updates CI/go.mod/docs for multi-repo local development.

Changes

Core refactor and infra updates

Layer / File(s) Summary
Actor/Identity API refactoring
pkg/identity/actor.go, pkg/registry/module.go, api/middleware/auth.go, api/middleware/auth_test.go, api/mcp/server.go, api/mcp/handlers_test.go, api/mcp/transport_test.go, tests/auth_test.go
Interface contracts changed to accept and return identity.Actor values instead of *identity.Actor pointers. TokenValidator, ActorResolver, and context helpers (WithActor, ForContext) now use non-pointer actor types. All implementations and test mocks updated to construct identity.BaseActor instances and assertions now use GetID().
Product model and GraphQL autobind
api/graph/api_test.go, api/gqlgen.yml, api/mcp/server.go
Product fixtures extended with Handle and Variants. GraphQL autobind list expanded to include commerce seo and taxonomy. MCP product dashboard price rendering now computes price from variants (N/A, single, or min–max range) and uses a new formatPrice helper.
Storage provider: in-process replacement
internal/storage/cloud.go, go.mod
CloudProvider no longer uses gocloud.dev; supports mem:// (in-memory map + RWMutex) and filesystem-backed storage. Upload/Open/Delete/GetURL/Close reimplemented to use in-memory buffers or filesystem operations. go.mod updated with local replace directives for auth, commerce, and mdk.
Workflow handler registration & codegen
pkg/workflow/runner.go, internal/app/app.go, cmd/hyperrr/root.go, internal/builder/codegen.go
Runner resolves step and compensation handlers only via Uses registry lookups (no inline Handler/Compensate fallback). system.about moved to a registered handler. Codegen emits direct returns for ActorResolver ID/Type/Name; other methods panic. Built-in auth CLI commands (auth apikey, auth user) statically registered.
Project setup: CI, docs, and build
.github/workflows/ci.yml, README.md, CHANGELOG.md, SECURITY.md, .coderabbit.yaml, pkg/config/config.go
CI workflow checks out dependent repos and generates a go.work multi-repo workspace, runs go vet/go test/go build. README updated to prefer go run ./cmd/builder and ./bin/hyperrr usage. New CHANGELOG and SECURITY policy added; CodeRabbit config adjusted; added CURRENCY config with default USD.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • GoHyperrr/hyperrr#1: Related CI/workspace build changes affecting the repository's build workflow.

Poem

🐰 I hopped through modules, stitched a workspace wide,

Actors learned to whisper, no pointers to hide.
Variants now trumpet prices near and far,
Storage keeps secrets in mem or local tar.
The rabbit tidied CI and signed the changelog star.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main changes: introducing ActorResolver methods, lightweight storage, and tests. It is concise, clear, and directly reflects the primary objectives.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/mdk-actor-interface

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
api/graph/api_test.go (1)

212-217: 🧹 Nitpick | 🔵 Trivial | 💤 Low value

Clarify the test case comment.

The comment states "missing name", but the input also sets Handle: "". The test validates that product creation fails when both Name and Handle are missing or empty. Consider updating the comment to accurately reflect what's being tested.

📝 Suggested comment clarification
-		// Create failure (missing name)
+		// Create failure (missing required fields: name and handle)
 		_, err = resolver.Mutation().CreateProduct(ctx, product.CreateProductInput{ID: "fail", Handle: ""})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/graph/api_test.go` around lines 212 - 217, Update the test comment to
accurately describe the failing input: it currently says "missing name" but the
call to resolver.Mutation().CreateProduct uses product.CreateProductInput{ID:
"fail", Handle: ""}, which omits both Name and Handle; change the comment to
state that the test ensures creation fails when Name and Handle are
missing/empty (or whichever precise combination you're asserting) so it matches
the input used by the CreateProduct call in the test.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 47-56: The go.work generation writes an invalid version directive
"go 1.25.5"; update the version line emitted by the CI step that writes go.work
so it uses a valid major.minor Go directive (e.g., "go 1.23" or whatever the
project's supported Go version is) instead of a patch-level value, ensuring the
echoed line that currently outputs `go 1.25.5` is replaced with the correct `go
X.Y` string.
- Around line 13-45: Replace all tag references for actions (the uses: entries
for actions/checkout@v4 and actions/setup-go@v5) with their specific commit SHAs
and add persist-credentials: false to every checkout step; update the steps
named "Checkout hyperrr", "Checkout mdk", "Checkout auth", "Checkout commerce",
and "Checkout file-storage" to include persist-credentials: false under their
with: blocks and change uses: actions/checkout@v4 to uses:
actions/checkout@<COMMIT_SHA>, and change "Setup Go" uses: actions/setup-go@v5
to uses: actions/setup-go@<COMMIT_SHA> (replace <COMMIT_SHA> with the verified
commit hashes).

In `@api/mcp/server.go`:
- Around line 928-954: The product currency is hardcoded to "USD" when rendering
the row; update the rendering to use the product's actual currency by replacing
the literal "USD" with the product or variant currency: check if p has a
Currency field (use p.Currency), otherwise fall back to the first variant's
currency (p.Variants[0].Currency); if variants may have mixed currencies, detect
that while iterating (compare each v.Currency) and show a sensible value like
"Multiple" or the first variant currency as a fallback; update the fmt.Sprintf
call that builds the row (references: p, p.Variants, priceStr, fmt.Sprintf) to
use that resolved currency variable instead of "USD".

In `@go.mod`:
- Line 74: Update the indirect dependency entry for golang.org/x/crypto in
go.mod from v0.51.0 to v0.52.0 (or newer) to resolve the SSH-related OSV
findings; locate the golang.org/x/crypto line in go.mod and change the version,
then run `go get golang.org/x/crypto@v0.52.0` (or `go get
golang.org/x/crypto@latest`) and `go mod tidy` followed by re-running the OSV
scan to verify the vulnerabilities are cleared.

In `@internal/builder/codegen.go`:
- Line 600: The nil-generation branch in internal/builder/codegen.go treats
"mdk.Actor" as nil (inside the if that checks strings.HasPrefix(part, "*") ||
strings.HasPrefix(part, "[]") || strings.HasPrefix(part, "map[") || part ==
"mdk.Actor"), which is wrong because mdk.Actor is a struct; update the logic
that builds zeroVals so that "mdk.Actor" is not classified as nil-able and
instead produces its struct zero-value (e.g., "mdk.Actor{}") when appending to
zeroVals; keep pointer, slice and map handling the same and only special-case
mdk.Actor to emit the struct literal.

In `@internal/storage/cloud.go`:
- Around line 69-72: The code currently buffers the entire incoming reader by
calling io.ReadAll(data) into buf which risks high memory usage; change the
filesystem storage path in internal/storage/cloud.go to stream the io.Reader
directly to disk instead of reading it into memory—create/open the destination
file (e.g., via os.Create or similar used in this module) and use io.Copy (or
io.CopyBuffer) to copy from the incoming data reader into the file, propagate
and handle any copy errors, and ensure the destination file is properly closed
and cleaned up on failure; replace the io.ReadAll + buf usage with this
streaming approach referencing the existing data variable and the file write
logic in this file.
- Line 132: Replace the naive fmt.Sprintf("%s/%s", strings.TrimSuffix(p.url,
"/"), path) with proper URL construction: parse p.url with net/url (url.Parse),
normalize the incoming path by converting OS separators with
filepath.ToSlash(path) for file:// on Windows, join URL paths with path.Join
(from package path) using the parsed base URL's Path, set the joined value into
the parsed url's Path (which will be correctly escaped) or use
url.ResolveReference, and return parsedURL.String(); update imports to include
net/url, path and filepath and remove the current string-concatenation logic
that produces duplicate slashes and misses encoding.

---

Outside diff comments:
In `@api/graph/api_test.go`:
- Around line 212-217: Update the test comment to accurately describe the
failing input: it currently says "missing name" but the call to
resolver.Mutation().CreateProduct uses product.CreateProductInput{ID: "fail",
Handle: ""}, which omits both Name and Handle; change the comment to state that
the test ensures creation fails when Name and Handle are missing/empty (or
whichever precise combination you're asserting) so it matches the input used by
the CreateProduct call in the test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 329ccacc-7ff7-47d9-a46a-b9dde2e2df88

📥 Commits

Reviewing files that changed from the base of the PR and between 9646bd0 and 478bdaa.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (20)
  • .github/workflows/ci.yml
  • CHANGELOG.md
  • README.md
  • SECURITY.md
  • api/gqlgen.yml
  • api/graph/api_test.go
  • api/mcp/handlers_test.go
  • api/mcp/server.go
  • api/mcp/transport_test.go
  • api/middleware/auth.go
  • api/middleware/auth_test.go
  • cmd/hyperrr/root.go
  • go.mod
  • internal/app/app.go
  • internal/builder/codegen.go
  • internal/storage/cloud.go
  • pkg/identity/actor.go
  • pkg/registry/module.go
  • pkg/workflow/runner.go
  • tests/auth_test.go

Comment thread .github/workflows/ci.yml
Comment on lines +13 to +45
- name: Checkout hyperrr
uses: actions/checkout@v4
with:
go-version: '1.25'
- run: go mod download
- run: go run ./cmd/builder
- run: go vet ./...
- run: go test -v -coverprofile=coverage.out ./...
- name: Go Coverage Report
uses: ncruces/go-coverage-report@v0
path: hyperrr

- name: Checkout mdk
uses: actions/checkout@v4
with:
repository: GoHyperrr/mdk
path: mdk

- name: Checkout auth
uses: actions/checkout@v4
with:
repository: GoHyperrr/auth
path: auth

- name: Checkout commerce
uses: actions/checkout@v4
with:
repository: GoHyperrr/commerce
path: commerce

- name: Checkout file-storage
uses: actions/checkout@v4
with:
report: 'true'
chart: 'true'
amend: 'true'
continue-on-error: true
repository: GoHyperrr/file-storage
path: file-storage

- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.25'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚖️ Poor tradeoff

Pin GitHub Actions to commit SHAs and disable credential persistence.

The workflow has two security posture gaps:

  1. Unpinned actions (lines 14, 19, 25, 31, 37, 43): Using tag references like @v4 and @v5 instead of commit SHAs allows maintainers to retroactively modify the action code, creating supply-chain risk.

  2. Missing persist-credentials: false in checkout steps: The default behavior persists the GitHub token in .git/config, making it available to subsequent steps and any scripts they execute.

🔒 Proposed fix

Pin actions to their commit hashes and disable credential persistence:

       - name: Checkout hyperrr
-        uses: actions/checkout@v4
+        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
         with:
           path: hyperrr
+          persist-credentials: false

       - name: Checkout mdk
-        uses: actions/checkout@v4
+        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
         with:
           repository: GoHyperrr/mdk
           path: mdk
+          persist-credentials: false

       - name: Checkout auth
-        uses: actions/checkout@v4
+        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
         with:
           repository: GoHyperrr/auth
           path: auth
+          persist-credentials: false

       - name: Checkout commerce
-        uses: actions/checkout@v4
+        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
         with:
           repository: GoHyperrr/commerce
           path: commerce
+          persist-credentials: false

       - name: Checkout file-storage
-        uses: actions/checkout@v4
+        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
         with:
           repository: GoHyperrr/file-storage
           path: file-storage
+          persist-credentials: false

       - name: Setup Go
-        uses: actions/setup-go@v5
+        uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
         with:

Note: Verify the commit SHAs above correspond to the desired versions before applying.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Checkout hyperrr
uses: actions/checkout@v4
with:
go-version: '1.25'
- run: go mod download
- run: go run ./cmd/builder
- run: go vet ./...
- run: go test -v -coverprofile=coverage.out ./...
- name: Go Coverage Report
uses: ncruces/go-coverage-report@v0
path: hyperrr
- name: Checkout mdk
uses: actions/checkout@v4
with:
repository: GoHyperrr/mdk
path: mdk
- name: Checkout auth
uses: actions/checkout@v4
with:
repository: GoHyperrr/auth
path: auth
- name: Checkout commerce
uses: actions/checkout@v4
with:
repository: GoHyperrr/commerce
path: commerce
- name: Checkout file-storage
uses: actions/checkout@v4
with:
report: 'true'
chart: 'true'
amend: 'true'
continue-on-error: true
repository: GoHyperrr/file-storage
path: file-storage
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.25'
- name: Checkout hyperrr
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
path: hyperrr
persist-credentials: false
- name: Checkout mdk
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
repository: GoHyperrr/mdk
path: mdk
persist-credentials: false
- name: Checkout auth
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
repository: GoHyperrr/auth
path: auth
persist-credentials: false
- name: Checkout commerce
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
repository: GoHyperrr/commerce
path: commerce
persist-credentials: false
- name: Checkout file-storage
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
repository: GoHyperrr/file-storage
path: file-storage
persist-credentials: false
- name: Setup Go
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
with:
go-version: '1.25'
🧰 Tools
🪛 zizmor (1.25.2)

[warning] 13-16: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[warning] 18-22: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[warning] 24-28: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[warning] 30-34: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[warning] 36-40: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 14-14: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 19-19: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 25-25: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 31-31: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 37-37: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 43-43: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 13 - 45, Replace all tag references
for actions (the uses: entries for actions/checkout@v4 and actions/setup-go@v5)
with their specific commit SHAs and add persist-credentials: false to every
checkout step; update the steps named "Checkout hyperrr", "Checkout mdk",
"Checkout auth", "Checkout commerce", and "Checkout file-storage" to include
persist-credentials: false under their with: blocks and change uses:
actions/checkout@v4 to uses: actions/checkout@<COMMIT_SHA>, and change "Setup
Go" uses: actions/setup-go@v5 to uses: actions/setup-go@<COMMIT_SHA> (replace
<COMMIT_SHA> with the verified commit hashes).

Source: Linters/SAST tools

Comment thread .github/workflows/ci.yml
Comment on lines +47 to +56
- name: Setup Workspace
run: |
echo "go 1.25.5" > go.work
echo "use (" >> go.work
echo " ./auth" >> go.work
echo " ./commerce" >> go.work
echo " ./file-storage" >> go.work
echo " ./hyperrr" >> go.work
echo " ./mdk" >> go.work
echo ")" >> go.work

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Invalid go.work version directive.

Line 49 specifies go 1.25.5, which has two problems:

  1. Go 1.25 does not exist (see previous comment)
  2. The go directive in go.work files requires major.minor format (e.g., go 1.23), not major.minor.patch
🔧 Proposed fix

Once the correct Go version is confirmed, update line 49:

-          echo "go 1.25.5" > go.work
+          echo "go 1.23" > go.work

(Replace 1.23 with the actual target version in major.minor format.)

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Setup Workspace
run: |
echo "go 1.25.5" > go.work
echo "use (" >> go.work
echo " ./auth" >> go.work
echo " ./commerce" >> go.work
echo " ./file-storage" >> go.work
echo " ./hyperrr" >> go.work
echo " ./mdk" >> go.work
echo ")" >> go.work
- name: Setup Workspace
run: |
echo "go 1.23" > go.work
echo "use (" >> go.work
echo " ./auth" >> go.work
echo " ./commerce" >> go.work
echo " ./file-storage" >> go.work
echo " ./hyperrr" >> go.work
echo " ./mdk" >> go.work
echo ")" >> go.work
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 47 - 56, The go.work generation writes
an invalid version directive "go 1.25.5"; update the version line emitted by the
CI step that writes go.work so it uses a valid major.minor Go directive (e.g.,
"go 1.23" or whatever the project's supported Go version is) instead of a
patch-level value, ensuring the echoed line that currently outputs `go 1.25.5`
is replaced with the correct `go X.Y` string.

Comment thread api/mcp/server.go Outdated
Comment thread go.mod Outdated
}

if strings.HasPrefix(part, "*") || strings.HasPrefix(part, "[]") || strings.HasPrefix(part, "map[") {
if strings.HasPrefix(part, "*") || strings.HasPrefix(part, "[]") || strings.HasPrefix(part, "map[") || part == "mdk.Actor" {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if mdk.Actor is defined as an interface type

ast-grep --pattern $'type Actor interface {
  $$$
}'

# Alternative: look for type Actor declaration
rg -n 'type Actor ' --type=go -g '**/mdk/**' -A3

Repository: GoHyperrr/hyperrr

Length of output: 210


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Locate mdk.Actor type definition =="
rg -n --type go '\btype\s+Actor\b' . || true
rg -n --type go '\btype\s+Actor\s+interface\b' . || true
rg -n --type go '\btype\s+Actor\s*=\s*interface\b' . || true
rg -n --type go '\bvar\s+Actor\b|\bconst\s+Actor\b' . || true

echo
echo "== Find mdk.Actor usages =="
rg -n --type go 'mdk\.Actor' internal/builder/codegen.go . || true

Repository: GoHyperrr/hyperrr

Length of output: 846


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Locate mdk package source =="
rg -n --type go '\bpackage\s+mdk\b' . || true
rg -n --type go '\bmodule\s+' go.mod || true
cat go.mod 2>/dev/null | sed -n '1,120p' || true

echo
echo "== Search for mdk.Actor definition patterns =="
# Only within repo first
rg -n --type go '\btype\s+Actor\b' . || true
rg -n --type go '\btype\s+Actor\s+interface\b' . || true
rg -n --type go '\btype\s+Actor\s+struct\b' . || true
rg -n --type go '\btype\s+Actor\s*=\s*interface\b' . || true

echo
echo "== If mdk is external: search go/pkg/mod (best-effort) for Actor interface/struct =="
if [ -d "$HOME/go/pkg/mod" ]; then
  rg -n --type go '\btype\s+Actor\s+interface\b' "$HOME/go/pkg/mod" 2>/dev/null | head -n 50 || true
  rg -n --type go '\bpackage\s+mdk\b' "$HOME/go/pkg/mod" 2>/dev/null | head -n 50 || true
  rg -n --type go '\btype\s+Actor\b' "$HOME/go/pkg/mod" 2>/dev/null | head -n 50 || true
else
  echo "No $HOME/go/pkg/mod directory found."
fi

Repository: GoHyperrr/hyperrr

Length of output: 4167


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Check local replace target ../mdk =="
ls -la ../mdk 2>/dev/null || echo "No ../mdk directory in sandbox."

echo
echo "== Search for type Actor in ../mdk (if present) =="
if [ -d ../mdk ]; then
  rg -n --type go '\btype\s+Actor\b' ../mdk || true
  rg -n --type go '\btype\s+Actor\s+interface\b' ../mdk || true
  rg -n --type go '\btype\s+Actor\s*=\s*interface\b' ../mdk || true
  rg -n --type go '\btype\s+Actor\s+struct\b' ../mdk || true
fi

echo
echo "== If mdk exists under current repo (vendored/submodule) search too =="
rg -n --type go '\btype\s+Actor\b' . -S -g '*mdk*' || true

Repository: GoHyperrr/hyperrr

Length of output: 257


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Go env =="
command -v go >/dev/null 2>&1 && go env GOPATH GOMODCACHE || true
echo

echo "== Check module cache directories =="
ls -la "${HOME}/go" 2>/dev/null || true
ls -la "${HOME}/go/pkg" 2>/dev/null || true
ls -la "${HOME}/go/pkg/mod" 2>/dev/null || true
echo

echo "== Find cached mdk module dirs (best-effort) =="
# common locations
for base in "${HOME}/go/pkg/mod" "${GOMODCACHE:-}"; do
  if [ -n "$base" ] && [ -d "$base" ]; then
    echo "-- searching in $base"
    # module cache dirs include @<version> in path
    fd -t d "mdk@" "$base" 2>/dev/null | head -n 20 || true
    fd -t d "*GoHyperrr*mdk*" "$base" 2>/dev/null | head -n 20 || true
  fi
done
echo

echo "== Search cached sources for `package mdk` and `type Actor` =="
# Try to locate any cached `github.com/!go!hyperrr/mdk@...` or similar escaped path
if [ -d "${HOME}/go/pkg/mod" ]; then
  rg -n --type go '\bpackage\s+mdk\b' "${HOME}/go/pkg/mod" 2>/dev/null | head -n 20 || true
  rg -n --type go '\btype\s+Actor\b' "${HOME}/go/pkg/mod" 2>/dev/null | head -n 50 || true
  rg -n --type go '\btype\s+Actor\s+interface\b' "${HOME}/go/pkg/mod" 2>/dev/null | head -n 50 || true
fi

Repository: GoHyperrr/hyperrr

Length of output: 1362


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Locate cached mdk module directory =="
# Search for directories whose path includes 'mdk' (case-insensitive)
find /home/jailuser/go/pkg/mod -maxdepth 8 -type d -iname '*mdk*' 2>/dev/null | head -n 50 || true

echo
echo "== Search in cached mdk sources for package mdk and type Actor =="
# Restrict to paths that look like the module we depend on to reduce noise
# (Go module cache escapes uppercase with !... patterns, so we search by 'mdk@' and 'mdk' in path)
mdk_dirs=$(find /home/jailuser/go/pkg/mod -maxdepth 10 -type d \( -iname '*mdk@*' -o -iname '*mdk*' \) 2>/dev/null | head -n 200 || true)

if [ -z "$mdk_dirs" ]; then
  echo "No cached directories matching '*mdk*' found under GOPATH/pkg/mod."
  exit 0
fi

# Try to find actual `package mdk` files and then `type Actor` within those dirs
echo "$mdk_dirs" | head -n 30

# Search for type Actor interface/struct/alias patterns across likely mdk dirs
echo
echo "== rg for 'package mdk' (limited) =="
echo "$mdk_dirs" | xargs -r rg -n --type go '^\s*package\s+mdk\b' 2>/dev/null | head -n 50 || true

echo
echo "== rg for 'type Actor' (limited) =="
echo "$mdk_dirs" | xargs -r rg -n --type go '\btype\s+Actor\b' 2>/dev/null | head -n 80 || true

echo
echo "== rg for Actor interface (limited) =="
echo "$mdk_dirs" | xargs -r rg -n --type go '\btype\s+Actor\s+interface\b' 2>/dev/null | head -n 80 || true

Repository: GoHyperrr/hyperrr

Length of output: 236


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== internal/builder/codegen.go around line 600 =="
nl -ba internal/builder/codegen.go | sed -n '560,640p'

echo
echo "== pkg/identity/actor.go =="
nl -ba pkg/identity/actor.go | sed -n '1,120p'

Repository: GoHyperrr/hyperrr

Length of output: 172


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== codegen.go (lines ~580-620) =="
sed -n '560,640p' internal/builder/codegen.go

echo
echo "== pkg/identity/actor.go =="
sed -n '1,120p' pkg/identity/actor.go

Repository: GoHyperrr/hyperrr

Length of output: 2476


🌐 Web query:

github.com/GoHyperrr/mdk type Actor

💡 Result:

There is no widely recognized project hosted at github.com/GoHyperrr/mdk as of June 6, 2026. It is possible that the repository is private, has been deleted, or the URL was mistyped. Searches for this specific GitHub path do not return any indexed results for an "Actor" type or library under that organization. In the context of software development, an "Actor" is a common programming abstraction used in the Actor Model for concurrent computation [1][2]. While several unrelated projects use the acronym "MDK" (often standing for "Media Development Kit" or "Moodle Development Kit") [3][4], the "Actor" type associated with MDK typically refers to specific legacy frameworks like the Datawire MDK (Microservices Development Kit), which defined a class Quark::MdkRuntime::Actors::Actor [5]. Other common implementations of the "Actor" type in Go exist in established libraries such as Proto.Actor [6] or GoAkt [1][2], but these are not affiliated with a "GoHyperrr" organization.

Citations:


🏁 Script executed:

# 1) Locate the dependency source on your machine
mdkdir="$(go list -f '{{.Dir}}' github.com/GoHyperrr/mdk)"

# 2) Find the actual Actor declaration
rg -n 'type\s+Actor\b' "$mdkdir" -S

# 3) Confirm the underlying kind in the matched line(s)
# (interface => nil-able; struct => nil is invalid)

Repository: GoHyperrr/hyperrr

Length of output: 207


🏁 Script executed:

#!/bin/bash
set -euo pipefail

if [ -d ../mdk ]; then
  rg -n --type go '\btype\s+Actor\b' ../mdk -S
else
  echo "Missing ../mdk (required by go.mod replace). Temporarily run: go mod edit -dropreplace github.com/GoHyperrr/mdk"
  echo "then: go mod download github.com/GoHyperrr/mdk@v0.0.0-20260605044506-3d2ab0d97ca9"
  mdkdir="$(go list -f '{{.Dir}}' github.com/GoHyperrr/mdk)"
  rg -n --type go '\btype\s+Actor\b' "$mdkdir" -S
fi

Repository: GoHyperrr/hyperrr

Length of output: 378


🏁 Script executed:

# 1) Temporarily disable the replace so `go` can download the module
go mod edit -dropreplace github.com/GoHyperrr/mdk

# 2) Download the required version
go mod download github.com/GoHyperrr/mdk@v0.0.0-20260605044506-3d2ab0d97ca9

# 3) Locate the module dir and inspect `Actor`
mdkdir="$(go list -f '{{.Dir}}' github.com/GoHyperrr/mdk)"
rg -n --type go '\btype\s+Actor\b' "$mdkdir" -S

Repository: GoHyperrr/hyperrr

Length of output: 184


Fix zero-value generation for mdk.Actor (it’s a struct, not nil-able)
internal/builder/codegen.go generates nil for any result token matching mdk.Actor:

if strings.HasPrefix(part, "*") || strings.HasPrefix(part, "[]") || strings.HasPrefix(part, "map[") || part == "mdk.Actor" {
	zeroVals = append(zeroVals, "nil")
}

But github.com/!go!hyperrr/mdk@v0.0.0-20260605044506-3d2ab0d97ca9/identity.go defines type Actor struct { ... }, so producing nil for an mdk.Actor struct is invalid and will fail to compile for generated code that uses this zero-value path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/builder/codegen.go` at line 600, The nil-generation branch in
internal/builder/codegen.go treats "mdk.Actor" as nil (inside the if that checks
strings.HasPrefix(part, "*") || strings.HasPrefix(part, "[]") ||
strings.HasPrefix(part, "map[") || part == "mdk.Actor"), which is wrong because
mdk.Actor is a struct; update the logic that builds zeroVals so that "mdk.Actor"
is not classified as nil-able and instead produces its struct zero-value (e.g.,
"mdk.Actor{}") when appending to zeroVals; keep pointer, slice and map handling
the same and only special-case mdk.Actor to emit the struct literal.

Comment thread internal/storage/cloud.go Outdated
Comment thread internal/storage/cloud.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.coderabbit.yaml:
- Line 9: Move the "tone_instructions" entry out of any nested map (e.g.,
reviews) and place it as a top-level key named exactly "tone_instructions" in
.coderabbit.yaml so CodeRabbit can read it; verify there is only one top-level
"tone_instructions" string (not under "reviews" or another section), and keep
the value as the desired review tone.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 00914531-feac-43ec-b65f-f8cfac90b70e

📥 Commits

Reviewing files that changed from the base of the PR and between 478bdaa and 553a809.

📒 Files selected for processing (1)
  • .coderabbit.yaml

Comment thread .coderabbit.yaml

reviews:
profile: "assertive"
tone_instructions: "Review code as a senior Go software engineer with a focus on concurrency safety, modular monolithic design boundaries, and clear error propagation."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

CodeRabbit configuration schema tone_instructions field documentation

💡 Result:

The tone_instructions field in the CodeRabbit configuration schema is used to customize the persona, style, and communication approach of CodeRabbit's review comments and chat responses [1][2][3][4]. Key details about the tone_instructions field: - Schema Type: It is defined as a string [2][3]. - Default Value: It defaults to an empty string (""), which results in CodeRabbit using its standard, default tone [1][2][3]. - Character Limit: The field has a maximum length of 250 characters [1][2]. - Functionality: You can provide natural language prompts to steer how CodeRabbit interacts [3][4]. For example, you can instruct it to be direct, adopt a specific persona (e.g., a nature documentary narrator or an energetic Scrum Master), or focus on specific communication styles like explaining the 'why' behind suggestions [3][4]. - Configuration Method: It is typically configured within the.coderabbit.yaml file located in the root of your repository [5][4]. It can also be set via the CodeRabbit Web UI under Settings > General > Tone Instructions [3]. While tone_instructions controls the overall communication style, it is distinct from other configuration fields such as reviews.instructions (which sets global review rules and conventions) and reviews.path_instructions (which applies context-aware guidance to specific file paths) [4][6][7]. [1][5][8]

Citations:


Fix/confirm tone_instructions placement in .coderabbit.yaml (line 9)

tone_instructions is a top-level string used to customize CodeRabbit’s overall review/chat tone; reviews.* keys are separate. If tone_instructions is nested under reviews, CodeRabbit may ignore it—keep it at the root and use the exact key name tone_instructions.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.coderabbit.yaml at line 9, Move the "tone_instructions" entry out of any
nested map (e.g., reviews) and place it as a top-level key named exactly
"tone_instructions" in .coderabbit.yaml so CodeRabbit can read it; verify there
is only one top-level "tone_instructions" string (not under "reviews" or another
section), and keep the value as the desired review tone.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
api/graph/api_test.go (1)

213-216: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Assert the failure reason, not just that an error occurred.

This check passes on any error, so it can mask regressions in required-field validation. Please assert the expected validation message/content (e.g., missing name/handle) to keep the test contract-specific.

Suggested patch
 		_, err = resolver.Mutation().CreateProduct(ctx, product.CreateProductInput{ID: "fail", Handle: ""})
-		if err == nil {
-			t.Error("expected error for invalid product create")
+		if err == nil || !strings.Contains(strings.ToLower(err.Error()), "name") || !strings.Contains(strings.ToLower(err.Error()), "handle") {
+			t.Errorf("expected validation error mentioning missing name and handle, got %v", err)
 		}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/graph/api_test.go` around lines 213 - 216, The test currently only checks
that resolver.Mutation().CreateProduct(ctx, product.CreateProductInput{ID:
"fail", Handle: ""}) returns an error; update the assertion to verify the error
reason by asserting the error message/content refers to the missing required
field (e.g., "missing name" or "handle is required"). Locate the failing call to
CreateProduct and replace the generic nil-check with an assertion that inspects
err.Error() (or uses errors.Is if a sentinel error is returned) to confirm the
validation message contains the expected substring for required-field validation
on product.CreateProductInput.Handle (and/or name).
internal/storage/cloud.go (3)

110-114: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Same path traversal vulnerability enables arbitrary file read.

Apply the same path validation as suggested for Upload to prevent reading files outside the storage directory.

🛡️ Proposed fix
 	fullPath := filepath.Join(p.baseDir, path)
+	absBase, _ := filepath.Abs(p.baseDir)
+	absPath, _ := filepath.Abs(fullPath)
+	if !strings.HasPrefix(absPath, absBase+string(os.PathSeparator)) && absPath != absBase {
+		return nil, fmt.Errorf("invalid path: escapes storage directory")
+	}
 	f, err := os.Open(fullPath)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/storage/cloud.go` around lines 110 - 114, The file read path
concatenation (fullPath := filepath.Join(p.baseDir, path); os.Open(fullPath)) is
vulnerable to path traversal; apply the same validation used in Upload: resolve
both p.baseDir and the joined fullPath to absolute paths (or use filepath.Rel)
and ensure the resulting path is within p.baseDir before calling os.Open. If the
check fails, return an error; keep references to the symbols p.baseDir,
fullPath, path and the Upload validation logic to locate and mirror the fix.

127-132: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Same path traversal vulnerability enables arbitrary file deletion.

Apply the same path validation as suggested for Upload and Open.

🛡️ Proposed fix
 	fullPath := filepath.Join(p.baseDir, path)
+	absBase, _ := filepath.Abs(p.baseDir)
+	absPath, _ := filepath.Abs(fullPath)
+	if !strings.HasPrefix(absPath, absBase+string(os.PathSeparator)) && absPath != absBase {
+		return fmt.Errorf("invalid path: escapes storage directory")
+	}
 	err := os.Remove(fullPath)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/storage/cloud.go` around lines 127 - 132, The delete routine
currently joins p.baseDir with the user-supplied path and removes it directly,
allowing path traversal; update the deletion logic to perform the same path
validation used by Upload and Open: clean the incoming path, compute the joined
fullPath, then verify that the resolved path is inside p.baseDir (e.g., using
filepath.Rel or equivalent) before calling os.Remove; if the resolved path lies
outside p.baseDir return an error and do not attempt deletion. Ensure you
reference the same checks applied in Upload and Open and protect uses of
p.baseDir and fullPath accordingly.

80-83: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Path traversal vulnerability allows arbitrary file write.

filepath.Join does not prevent directory traversal. A malicious path like ../../../etc/cron.d/backdoor would escape baseDir and write anywhere on the filesystem.

Validate that the resolved path remains within baseDir after joining.

🛡️ Proposed fix to add path traversal check
 	fullPath := filepath.Join(p.baseDir, path)
+	// Prevent path traversal by ensuring fullPath is within baseDir
+	absBase, _ := filepath.Abs(p.baseDir)
+	absPath, _ := filepath.Abs(fullPath)
+	if !strings.HasPrefix(absPath, absBase+string(os.PathSeparator)) && absPath != absBase {
+		return "", fmt.Errorf("invalid path: escapes storage directory")
+	}
 	if err := os.MkdirAll(filepath.Dir(fullPath), 0755); err != nil {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/storage/cloud.go` around lines 80 - 83, The code uses
filepath.Join(p.baseDir, path) to build fullPath but doesn't validate path
traversal; compute the cleaned absolute/resolved paths (use filepath.Clean +
filepath.Abs or filepath.Rel) and verify that fullPath is inside p.baseDir
(e.g., reject when filepath.Rel(p.baseDir, fullPath) starts with ".." or when
the resolved path does not have p.baseDir as a prefix) before calling
os.MkdirAll or writing files; if the check fails, return an error. Ensure you
reference the variables fullPath, p.baseDir and the incoming path when adding
the validation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/storage/cloud.go`:
- Around line 85-93: The current pattern creates a file with os.Create(fullPath)
and defers f.Close(), but if io.Copy(f, data) fails the incomplete file remains;
change the error path so that when io.Copy returns an error you explicitly close
f (call f.Close()) and remove the partial file with os.Remove(fullPath) before
returning the error; keep the normal defer f.Close() for the success path but
ensure the cleanup (Close + Remove) happens on io.Copy error to avoid leaving
partial files.

---

Outside diff comments:
In `@api/graph/api_test.go`:
- Around line 213-216: The test currently only checks that
resolver.Mutation().CreateProduct(ctx, product.CreateProductInput{ID: "fail",
Handle: ""}) returns an error; update the assertion to verify the error reason
by asserting the error message/content refers to the missing required field
(e.g., "missing name" or "handle is required"). Locate the failing call to
CreateProduct and replace the generic nil-check with an assertion that inspects
err.Error() (or uses errors.Is if a sentinel error is returned) to confirm the
validation message contains the expected substring for required-field validation
on product.CreateProductInput.Handle (and/or name).

In `@internal/storage/cloud.go`:
- Around line 110-114: The file read path concatenation (fullPath :=
filepath.Join(p.baseDir, path); os.Open(fullPath)) is vulnerable to path
traversal; apply the same validation used in Upload: resolve both p.baseDir and
the joined fullPath to absolute paths (or use filepath.Rel) and ensure the
resulting path is within p.baseDir before calling os.Open. If the check fails,
return an error; keep references to the symbols p.baseDir, fullPath, path and
the Upload validation logic to locate and mirror the fix.
- Around line 127-132: The delete routine currently joins p.baseDir with the
user-supplied path and removes it directly, allowing path traversal; update the
deletion logic to perform the same path validation used by Upload and Open:
clean the incoming path, compute the joined fullPath, then verify that the
resolved path is inside p.baseDir (e.g., using filepath.Rel or equivalent)
before calling os.Remove; if the resolved path lies outside p.baseDir return an
error and do not attempt deletion. Ensure you reference the same checks applied
in Upload and Open and protect uses of p.baseDir and fullPath accordingly.
- Around line 80-83: The code uses filepath.Join(p.baseDir, path) to build
fullPath but doesn't validate path traversal; compute the cleaned
absolute/resolved paths (use filepath.Clean + filepath.Abs or filepath.Rel) and
verify that fullPath is inside p.baseDir (e.g., reject when
filepath.Rel(p.baseDir, fullPath) starts with ".." or when the resolved path
does not have p.baseDir as a prefix) before calling os.MkdirAll or writing
files; if the check fails, return an error. Ensure you reference the variables
fullPath, p.baseDir and the incoming path when adding the validation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f6c20116-c9a4-436b-8d02-79523dd80bb8

📥 Commits

Reviewing files that changed from the base of the PR and between 553a809 and 0952b7e.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (4)
  • SECURITY.md
  • api/graph/api_test.go
  • go.mod
  • internal/storage/cloud.go

Comment thread internal/storage/cloud.go
Comment on lines +85 to 93
f, err := os.Create(fullPath)
if err != nil {
return "", err
}
if err := w.Close(); err != nil {
defer f.Close()

if _, err := io.Copy(f, data); err != nil {
return "", err
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Partial file left on disk if io.Copy fails.

When io.Copy fails after the file is created, defer f.Close() runs but the incomplete file remains. This can leave corrupted data or consume disk space unexpectedly.

🧹 Proposed fix to clean up on failure
 	f, err := os.Create(fullPath)
 	if err != nil {
 		return "", err
 	}
-	defer f.Close()
 
 	if _, err := io.Copy(f, data); err != nil {
+		f.Close()
+		os.Remove(fullPath)
 		return "", err
 	}
+	if err := f.Close(); err != nil {
+		os.Remove(fullPath)
+		return "", err
+	}
 
 	return path, nil
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
f, err := os.Create(fullPath)
if err != nil {
return "", err
}
if err := w.Close(); err != nil {
defer f.Close()
if _, err := io.Copy(f, data); err != nil {
return "", err
}
f, err := os.Create(fullPath)
if err != nil {
return "", err
}
if _, err := io.Copy(f, data); err != nil {
f.Close()
os.Remove(fullPath)
return "", err
}
if err := f.Close(); err != nil {
os.Remove(fullPath)
return "", err
}
return path, nil
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/storage/cloud.go` around lines 85 - 93, The current pattern creates
a file with os.Create(fullPath) and defers f.Close(), but if io.Copy(f, data)
fails the incomplete file remains; change the error path so that when io.Copy
returns an error you explicitly close f (call f.Close()) and remove the partial
file with os.Remove(fullPath) before returning the error; keep the normal defer
f.Close() for the success path but ensure the cleanup (Close + Remove) happens
on io.Copy error to avoid leaving partial files.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
.github/workflows/ci.yml (2)

53-53: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fix invalid go.work version directive format.

Line 53 writes go 1.25.5; go.work requires major.minor (for example, go 1.25). This can break workspace parsing and downstream go commands in CI.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml at line 53, The CI step writes an invalid Go
workspace directive "go 1.25.5" into go.work; update the echo that writes
go.work so the directive uses major.minor only (e.g., "go 1.25") instead of "go
1.25.5" — locate the line that outputs the string "go 1.25.5" to go.work and
change it to "go 1.25" (or derive the major.minor from your GO_VERSION variable)
so the go.work file conforms to the required format.

13-47: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Pin actions and disable credential persistence in checkout steps.

This remains unresolved: Line 14/19/26/33/40 use tag-pinned actions and checkout steps still persist credentials by default. Please pin all actions to commit SHAs and set persist-credentials: false in each checkout with: block.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 13 - 47, Replace all tag-pinned action
references with their corresponding commit SHAs and add persist-credentials:
false to each checkout step's with: block; specifically update the uses entries
for actions/checkout@v4 in the "Checkout hyperrr", "Checkout mdk", "Checkout
auth", "Checkout commerce", and "Checkout file-storage" steps to the commit SHAs
and add persist-credentials: false under each with:, and also pin
actions/setup-go@v5 to its commit SHA (replace uses: actions/setup-go@v5 with
the SHA-pinned ref).

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 22-23: The workflow currently uses a cross-repo branch expression
"ref: ${{ github.head_ref || github.ref_name }}" (seen next to "path: mdk")
which assumes matching branches exist in dependent repos; change these checkout
actions to use a stable fallback or explicit per-repo ref instead — e.g.,
replace the expression with a conditional that falls back to the repository
default branch (or a repo-specific input/variable) for the mdk checkout, and
apply the same change to the other occurrences (the other "ref: ${{
github.head_ref || github.ref_name }}" lines) so CI no longer fails when feature
branches aren't present in every repo.

In `@api/mcp/server.go`:
- Around line 928-936: The code assigns p.Metadata["currency"] to currencyCode
even when it's an empty string, causing formatPrice output with a trailing
space; update the assignment in the block that checks p.Metadata (around the
currencyCode variable and the p.Metadata["currency"] type assertion) to only set
currencyCode when the asserted string is non-empty (e.g., check curr != "" or
strings.TrimSpace(curr) != "") so that empty metadata values fallback to the
Config/default USD instead of overwriting with an empty string.

---

Duplicate comments:
In @.github/workflows/ci.yml:
- Line 53: The CI step writes an invalid Go workspace directive "go 1.25.5" into
go.work; update the echo that writes go.work so the directive uses major.minor
only (e.g., "go 1.25") instead of "go 1.25.5" — locate the line that outputs the
string "go 1.25.5" to go.work and change it to "go 1.25" (or derive the
major.minor from your GO_VERSION variable) so the go.work file conforms to the
required format.
- Around line 13-47: Replace all tag-pinned action references with their
corresponding commit SHAs and add persist-credentials: false to each checkout
step's with: block; specifically update the uses entries for actions/checkout@v4
in the "Checkout hyperrr", "Checkout mdk", "Checkout auth", "Checkout commerce",
and "Checkout file-storage" steps to the commit SHAs and add
persist-credentials: false under each with:, and also pin actions/setup-go@v5 to
its commit SHA (replace uses: actions/setup-go@v5 with the SHA-pinned ref).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 10409f49-f938-48af-9134-5fb836649ed2

📥 Commits

Reviewing files that changed from the base of the PR and between 0952b7e and 28a0ee8.

📒 Files selected for processing (3)
  • .github/workflows/ci.yml
  • api/mcp/server.go
  • pkg/config/config.go

Comment thread .github/workflows/ci.yml
Comment on lines +22 to +23
ref: ${{ github.head_ref || github.ref_name }}
path: mdk

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Cross-repo branch coupling can make PR CI fail non-deterministically.

Using ref: ${{ github.head_ref || github.ref_name }} for mdk/auth/commerce/file-storage assumes the same branch exists in every repository. For most feature branches, checkout will fail before vet/test/build. Use a stable fallback (e.g., default branch) or make per-repo refs explicit.

Also applies to: 29-30, 36-37, 43-44

🧰 Tools
🪛 zizmor (1.25.2)

[warning] 18-23: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 22 - 23, The workflow currently uses a
cross-repo branch expression "ref: ${{ github.head_ref || github.ref_name }}"
(seen next to "path: mdk") which assumes matching branches exist in dependent
repos; change these checkout actions to use a stable fallback or explicit
per-repo ref instead — e.g., replace the expression with a conditional that
falls back to the repository default branch (or a repo-specific input/variable)
for the mdk checkout, and apply the same change to the other occurrences (the
other "ref: ${{ github.head_ref || github.ref_name }}" lines) so CI no longer
fails when feature branches aren't present in every repo.

Comment thread api/mcp/server.go
Comment on lines +928 to +936
currencyCode := "USD"
if s.deps.Config != nil && s.deps.Config.Currency != "" {
currencyCode = s.deps.Config.Currency
}
if p.Metadata != nil {
if curr, ok := p.Metadata["currency"].(string); ok {
currencyCode = curr
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial | 💤 Low value

Consider validating non-empty currency from metadata.

If p.Metadata["currency"] contains an empty string, the type assertion succeeds and currencyCode becomes empty, causing formatPrice to produce output like "123.45 " with a trailing space.

🔧 Proposed fix
 if p.Metadata != nil {
-    if curr, ok := p.Metadata["currency"].(string); ok {
+    if curr, ok := p.Metadata["currency"].(string); ok && curr != "" {
         currencyCode = curr
     }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/mcp/server.go` around lines 928 - 936, The code assigns
p.Metadata["currency"] to currencyCode even when it's an empty string, causing
formatPrice output with a trailing space; update the assignment in the block
that checks p.Metadata (around the currencyCode variable and the
p.Metadata["currency"] type assertion) to only set currencyCode when the
asserted string is non-empty (e.g., check curr != "" or strings.TrimSpace(curr)
!= "") so that empty metadata values fallback to the Config/default USD instead
of overwriting with an empty string.

@inf3cti0n95 inf3cti0n95 merged commit 700b269 into main Jun 6, 2026
2 checks passed
@inf3cti0n95 inf3cti0n95 deleted the feature/mdk-actor-interface branch June 6, 2026 06:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant